package com.powergisol.core.analysis;


import com.powergisol.core.math.Dot;
import com.powergisol.core.math.Vector;


public class SpatialAnalysis {
    /**
     * 这次修改成了8
     */
    private final static int PRECISION = 8;
    /**
     * 求平面中两个向量的叉积
     *
     * @param vectorA
     * @param vectorB
     * @return
     */
    public static double det2D(Vector vectorA, Vector vectorB) {

        double x1, y1, x2, y2;
        x1 = vectorA.getX();
        y1 = vectorA.getY();
        x2 = vectorB.getX();
        y2 = vectorB.getY();

        return det2D(x1, y1, x2, y2,PRECISION);
    }


    /**
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     * @return
     */
    public static double det2D(double x1, double y1, double x2, double y2) {

        return x1 * y2 - x2 * y1;
    }


    /**
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     * @return
     */
    public static double det2D(double x1, double y1, double x2, double y2,int precision) {

        double reslutA = compute(x1,precision) * compute(y2,precision);
        double reslutB = compute(x2,precision) * compute(y1,precision);

        return reslutA-reslutB;
    }

    /**
     * 对一个小数的多少位进行四舍五入
     * @param num
     * @param precision 保留小数多少位,必须大于0
     * @return
     */

    public static double compute(double num, int precision){

        if(precision<0){
            throw new RuntimeException("精度必须为正整数!");
        }

        double pow = Math.pow(10, precision);
        return (double)Math.round(num*pow)/pow;

    }

    /**
     * 判断平面中点是否在三角形内
     *
     * @param x0
     * @param y0
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     * @param x3
     * @param y3
     * @return
     */
    public static boolean checkDotInTriangleMesh2D(double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3) {
        double resultA = det2D(x2 - x1, y2 - y1, x0 - x1, y0 - y1) * det2D(x3 - x2, y3 - y2, x0 - x2, y0 - y2);
        double resultB = det2D(x3 - x2, y3 - y2, x0 - x2, y0 - y2) * det2D(x1 - x3, y1 - y3, x0 - x3, y0 - y3);

        return (resultA >= 0 && resultB >= 0);

    }

    /**
     * 判断dotO 点 是否在 dotA,dotB,dotC 所在的三角形内
     * @param dotO
     * @param dotA
     * @param dotB
     * @param dotC
     * @return
     */
    public static boolean checkDotInTriangleMesh2D(Dot dotO, Dot dotA,Dot dotB,Dot dotC) {

        Vector vectorAO = new Vector(dotA,dotO);
        Vector vectorAB = new Vector(dotA,dotB);


        Vector vectorBC = new Vector(dotB,dotC);
        Vector vectorBO = new Vector(dotO,dotC);

        Vector vectorCA = new Vector(dotC,dotA);
        Vector vectorCO = new Vector(dotC,dotO);

        double resultA = det2D(vectorAB,vectorAO);
        double resultB = det2D(vectorBC,vectorBO);
        double resultC = det2D(vectorCA,vectorCO);
        //证明三个方向相同,就说明doto在三角形ABC内,无所谓ABC逆向还是正向

        return (resultA*resultB >= 0 && resultB*resultC >= 0);

    }

    /**
     * 判断三个点是否按照逆时针排序
     *
     * @param pointA [xa,ya]
     * @param pointB [xb,yb]
     * @param pointC [xc,yc]
     * @return
     */
    public static boolean isReverse(double[] pointA, double[] pointB, double[] pointC) {

        double v1X = pointB[0] - pointA[0];
        double v1Y = pointB[1] - pointA[1];

        double v2X = pointC[0] - pointA[0];
        double v2Y = pointC[1] - pointA[1];

        return det2D(v1X,v1Y,v2X,v2Y) > 0;

    }


    public static boolean isReverse(Dot dotA, Dot dotB, Dot dotC) {

        Vector vectorAB = new Vector(dotA, dotB);
        Vector vectorAC = new Vector(dotA, dotC);

        return det2D(vectorAB, vectorAC) > 0;

    }

}
